
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkAAClip.h"
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkImageDecoder.h"

#ifdef SK_BUILD_FOR_WIN
// windows doesn't have roundf
inline float roundf(float x)
    {
    return (x-floor(x))>0.5 ? ceil(x) : floor(x);
    }
#endif

static void drawClip(SkCanvas* canvas, const SkAAClip& clip)
    {
    SkMask mask;
    SkBitmap bm;

    clip.copyToMask(&mask);
    SkAutoMaskFreeImage amfi(mask.fImage);

    bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
                 mask.fBounds.height(), mask.fRowBytes);
    bm.setPixels(mask.fImage);

    SkPaint paint;
    canvas->drawBitmap(bm,
                       SK_Scalar1 * mask.fBounds.fLeft,
                       SK_Scalar1 * mask.fBounds.fTop,
                       &paint);
    }

static void paint_rgn(SkCanvas* canvas, const SkAAClip& clip,
                      const SkPaint& paint)
    {
    SkMask mask;
    SkBitmap bm;

    clip.copyToMask(&mask);
    SkAutoMaskFreeImage amfi(mask.fImage);

    bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
                 mask.fBounds.height(), mask.fRowBytes);
    bm.setPixels(mask.fImage);

    canvas->drawBitmap(bm,
                       SK_Scalar1 * mask.fBounds.fLeft,
                       SK_Scalar1 * mask.fBounds.fTop,
                       &paint);
    }

class AAClipView2 : public SampleView
    {
    public:
        AAClipView2()
            {
            fBase.set(100, 100, 150, 150);
            fRect = fBase;
            fRect.inset(5, 5);
            fRect.offset(25, 25);
            this->setBGColor(0xFFDDDDDD);
            }

        static void setAAClip(SkAAClip* clip, const SkIRect& rect)
            {
            SkRect r;
            r.set(rect);
            SkPath path;
            path.addRoundRect(r, SkIntToScalar(5), SkIntToScalar(5));
            clip->setPath(path);
            }

        void build_rgn(SkAAClip* clip, SkRegion::Op op)
            {
            setAAClip(clip, fBase);

            SkAAClip clip2;
            setAAClip(&clip2, fRect);
            clip->op(clip2, op);
            }


    protected:
        // overrides from SkEventSink
        virtual bool onQuery(SkEvent* evt)
            {
            if (SampleCode::TitleQ(*evt))
                {
                SampleCode::TitleR(evt, "AAClips");
                return true;
                }
            return this->INHERITED::onQuery(evt);
            }

        void drawOrig(SkCanvas* canvas, bool bg)
            {
            SkRect      r;
            SkPaint     paint;

            paint.setStyle(SkPaint::kStroke_Style);
            if (bg)
                paint.setColor(0xFFBBBBBB);

            r.set(fBase);
            canvas->drawRect(r, paint);
            r.set(fRect);
            canvas->drawRect(r, paint);
            }

        static void outer_frame(SkCanvas* canvas, const SkIRect& rect)
            {
            SkRect r;
            r.set(rect);
            r.inset(-SK_ScalarHalf, -SK_ScalarHalf);

            SkPaint paint;
            paint.setColor(SK_ColorGRAY);
            paint.setStyle(SkPaint::kStroke_Style);
            canvas->drawRect(r, paint);
            }

        void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color)
            {
            SkAAClip clip;

            this->build_rgn(&clip, op);

            this->drawOrig(canvas, true);

            SkPaint paint;
            paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
            paint_rgn(canvas, clip, paint);

            paint.setStyle(SkPaint::kStroke_Style);
            paint.setColor(color);
            paint_rgn(canvas, clip, paint);

            SkAAClip clip2(clip);
            clip2.translate(0, 80);
            outer_frame(canvas, clip2.getBounds());
            paint_rgn(canvas, clip2, paint);
            }

        virtual void onDrawContent(SkCanvas* canvas)
            {

            static const struct
                {
                SkColor         fColor;
                const char*     fName;
                SkRegion::Op    fOp;
                } gOps[] =
                {
                    { SK_ColorBLACK,    "Difference",   SkRegion::kDifference_Op    },
                    { SK_ColorRED,      "Intersect",    SkRegion::kIntersect_Op     },
                    { 0xFF008800,       "Union",        SkRegion::kUnion_Op         },
                    { SK_ColorBLUE,     "XOR",          SkRegion::kXOR_Op           }
                };

            SkPaint textPaint;
            textPaint.setAntiAlias(true);
            textPaint.setTextSize(SK_Scalar1*24);

            this->drawOrig(canvas, false);

            canvas->translate(0, SkIntToScalar(200));

            for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++)
                {
                canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), SkIntToScalar(75), SkIntToScalar(50), textPaint);

                this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);

                canvas->translate(SkIntToScalar(200), 0);
                }
            }

        virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
            {
            return fRect.contains(SkScalarRound(x), SkScalarRound(y)) ? new Click(this) : NULL;
            }

        virtual bool onClick(Click* click)
            {
            fRect.offset(click->fICurr.fX - click->fIPrev.fX,
                         click->fICurr.fY - click->fIPrev.fY);
            this->inval(NULL);
            return true;
            }

    private:
        SkIRect    fBase, fRect;

        typedef SampleView INHERITED;
    };

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory()
    {
    return new AAClipView2;
    }
static SkViewRegister reg(MyFactory);

